for Monitoring Data Collection
2026-05-12
.qmd ecosystem# ## ### headings and size controlR Markdown combines narrative text (markdown) with executable code chunks (usually R) into a single dynamic document.
Quarto is the next-generation R Markdown from Posit, same idea, more features, multi-language.
.qmd.Rmd files render unchangedLive example
My personal site is built with Quarto: https://yebelay.rbind.io/
If you know R Markdown, you already know most of Quarto. Here’s what changed:
| Aspect | R Markdown | Quarto |
|---|---|---|
| File format | .Rmd |
.qmd |
| Engine | knitr only |
knitr + Jupyter |
| Languages | Mainly R | R, Python, Julia, Observable |
| Output formats | Via rmarkdown package |
Built-in, unified YAML |
| YAML option | output: html_document |
format: dashboard |
| Chunk options | ```{r echo=FALSE} |
#| echo: false (inline) |
| Dashboards | flexdashboard package |
format: dashboard (built-in) |
Tip
Think of Quarto as one tool for everything you currently do across rmarkdown, bookdown, xaringan, and flexdashboard.
A single .qmd file that renders into a fully interactive web dashboard (no Shiny server required for static content).
📁 One file
Structure, code, and text live together in a single .qmd.
🚀 No server
Renders to a standalone .html you can email or host.
🔬 Multiple languages
Use the right engine: R, Python, Julia, or Observable.
Tip
A dashboard is just a .qmd file with format: dashboard in the YAML.
.qmd File.qmd fileknitr (or Jupyter) runs your code chunks.html is saved alongside the .qmdTip
Save the file as dashboard.qmd, then click Render (Ctrl+Shift+K in RStudio).
_quarto.yml
---
title: "C4ED Programme Monitor"
author: "Yebelay"
format:
dashboard:
theme: flatly # bootswatch theme
orientation: rows # rows (default)
logo: logo.png # nav bar logo
scrolling: true # allow scrolling
expandable: true # fullscreen cards
execute:
echo: false # hide all code
warning: false
message: false
---| Option | What it does |
|---|---|
theme: |
Built-in Bootswatch: flatly, cosmo, minty, darkly… |
orientation: |
rows (default) → ## creates rows · columns → ## creates columns |
scrolling: |
true allows the page to scroll; false pins card heights |
echo: false |
Always set this - hides all R/Python code from output |
expandable: |
Adds a fullscreen button to every card automatically |
Important
Set echo: false globally in execute: - never per-chunk - so code is never accidentally exposed to stakeholders.
Top bar with the icon, title, author, and links to each # page.
Pages, rows, columns, and tabsets - all defined by Markdown headings (#, ##, ###).
Cards display output. Sidebars hold filters. Toolbars add inline inputs.
Important
The rule: # → ## → ### → chunk. Skipping a level breaks the layout.
| Level | Syntax | Creates | Key attribute |
|---|---|---|---|
| 1 | # Page name |
Navigation tab in top bar | background-color= |
| 2 | ## Row name |
Horizontal row band | {height=N%} · {.tabset} · {.sidebar} |
| 3 | ### Col name |
Column inside a row | {width=N%} |
| – | ```{r} chunk |
One card inside a column | #| title: · #| fig-height: |
| – | content: valuebox |
KPI value box | #| icon: · #| color: |
Tip
The hierarchy is always # → ## → ### → chunk.
###rows.qmd
Rules
## creates a full-width horizontal band{height=N%} to control the vertical splitNote
Heights should sum to ~100%. Quarto distributes leftover space automatically if they don’t.
###| Heading | Default (orientation: rows) |
With orientation: columns |
|---|---|---|
## |
Horizontal row | Vertical column |
### |
Column inside row | Row inside column |
{height=N%} |
On ## row |
On ### row |
{width=N%} |
On ### column |
On ## column |
Every code chunk output is automatically wrapped in a card. The #| title: option sets the card header.
Tip
#| expandable: true adds a fullscreen button to any card.
Tip
Find icon names at https://icons.getbootstrap.com - search any concept and copy the name (e.g. graph-up, geo-alt-fill, people-fill).
page1_overview.qmd
# Overview
## KPIs {height=20%}
```{r}
#| content: valuebox
#| title: "Beneficiaries"
#| icon: people-fill
#| color: "#047B77"
list(value = scales::comma(sum(df$reach)))
```
```{r}
#| content: valuebox
#| title: "Woredas"
#| color: "#1A9490"
list(value = n_distinct(df$woreda))
```
## Charts {height=78% .tabset}
### By team
```{r}
#| title: "Reach by team"
ggplot(df, aes(team, reach, fill = team)) +
geom_col() + theme_c4ed()
```Note
Result: three KPI value boxes on top, a tabbed chart row below. Same skeleton works for every monitoring dashboard.
Rules
{.tabset} to a ## Row heading to activate### sub-headings become individual tab labelsTip
Use tabsets when you have 3+ views of the same data. For 2 views, side-by-side columns often look cleaner.
The same data, three lenses - click the tabs:
| team | reach |
|---|---|
| A | 412 |
| B | 538 |
| C | 297 |
| D | 614 |
| E | 480 |
dashboard.qmd
---
title: "C4ED Programme Dashboard"
format:
dashboard:
theme: flatly
orientation: rows
scrolling: true
logo: img/c4ed_logo.png
execute:
echo: false
warning: false
---
```{r setup, include=FALSE}
library(ggplot2); library(dplyr)
library(DT); library(leaflet)
df <- readr::read_csv("data/field_data.csv")
```
# Overview # value boxes + charts
# Daily # trend + map + table
# Data # interactive DT tables
# KPI # summary statsBuild in this order
setup chunk# page headings## rows (with {height=N%})### columns (with {width=N%})Ctrl+Shift+K)# ## ### headings with placeholder text. Render to check layout before any code.ggplot() calls in one chunk if you want separate cards.echo: false globally - set in YAML execute: block once. Never accidentally expose code to stakeholders.{r valuebox-reach}, {r chart-country} make debugging much faster.| Error | Fix |
|---|---|
| Blank white page | Check YAML indentation |
| Cards overlapping | Reduce {height=N%} values |
| Code visible in output | Add echo: false in execute: |
| Empty value box | Return must be a list() |
| Icon not showing | Check spelling on icons.getbootstrap.com |
| “skipped heading level” warning | Don’t jump from # to ### - go through ## |
quick_ref.qmd
# Structure (Markdown headings)
# Page # navigation tab
## Row # horizontal band {height=N%}
### Column # column in row {width=N%}
# Row/column modifiers
{.tabset} # tabbed row
{.sidebar} # left sidebar panel
{.scrollable} # allow row to scroll
{.fill} # stretch to fill row
# Code chunk options
#| content: valuebox # make a value box
#| title: "label" # card header title
#| icon: people # Bootstrap icon name
#| color: "#047B77" # background color
#| fig-height: 4 # plot height (inches)
#| fig-width: 8 # plot width
#| padding: 0px # remove card padding
#| expandable: true # fullscreen buttonResources
Tip
Add server: shiny to YAML → full Shiny app. Then use input$ and output$ as normal.
Live demo: https://yebelay.github.io/llrp-dashboard/
Thank you!
Yebelay Berehan. C4ED Ethiopia ·
yebelay.berehan@c4ed.org

Quarto Dashboards · Internal seminar · May 12, 2026